package com.alan.mongodb.elasticsearch;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;

import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Auther: Alan liu
 * @Date: 2019/9/27 17:48
 * @Description: ElasticService
 */
@Slf4j
public class ElasticService {
    private TransportClient client = null;

    private static final ThreadLocal<SimpleDateFormat> dateInfoFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat(
                    "yyyy-MM-dd'T'HH:mm:ss.SSS");
        }
    };
    private static final String INDEX_NAME = "alan_test";
    private static final String TYPE_NAME = "alan_doc";
    /**
     * 创建索引
     *
     * @throws UnknownHostException
     */
    private void createIndex() throws Exception {
        //创建index索引，设置6个分片，2个副本
        CreateIndexResponse indexResponse = client.admin().indices().prepareCreate(INDEX_NAME)
                .setSettings(Settings.builder().put("index.number_of_shards", 6).put("index.number_of_replicas", 2))
                .get();
        log.info("索引是否创建成功: {}", indexResponse.isAcknowledged());
        //建立别名
//        IndicesAliasesResponse response = client.admin().indices().prepareAliases().addAlias(index, alias).get();
//        log.info("索引别名是否创建成功: {}", response.isAcknowledged());

    }

    /**
     * 创建doc的mapping
     * @throws Exception
     */
    private void createDocumentMap() throws Exception {
        if (!indexExists()) {
            //创建索引
            createIndex();
            // 构建索引映射
            XContentBuilder builder = XContentFactory.jsonBuilder()
                    .startObject().field("properties")
                    .startObject()
                    .field("orderNo").startObject().field("type", "string").endObject()
                    .field("fromMail").startObject().field("type", "string").endObject()
                    .field("fromUserName").startObject().field("type", "string").endObject()
                    .field("toMail").startObject().field("type", "string").endObject()
                    .field("toCc").startObject().field("type", "string").endObject()
                    .field("title").startObject().field("type", "string").endObject()
                    .field("content").startObject().field("type", "string").endObject()
                    .field("attachment").startObject().field("type", "string").endObject()
                    .field("status").startObject().field("type", "string").endObject()
                    .field("errMsg").startObject().field("type", "string").endObject()
                    .field("sendTime").startObject().field("type", "date").endObject()
                    .endObject()
                    .endObject();
            // 将映射写入对应index,type中
            PutMappingRequest mappingRequest = Requests.putMappingRequest(INDEX_NAME).source(builder).type(TYPE_NAME);
            client.admin().indices().putMapping(mappingRequest).actionGet();
        } else {
            log.info("索引已存在!");
        }

    }

    /**
     * 索引是否存在
     * @return
     * @throws UnknownHostException
     */
    public boolean indexExists() throws Exception {
        IndicesExistsRequest request = new IndicesExistsRequest(INDEX_NAME);
        IndicesExistsResponse response = client.admin().indices().exists(request).actionGet();
        if (response.isExists()) {
            return true;
        }
        return false;
    }

    /**
     * 删除索引
     * @return
     * @throws UnknownHostException
     */
    public boolean deleteIndex(String index) throws Exception {
        AcknowledgedResponse dResponse = client.admin().indices().prepareDelete(index).execute().actionGet();
        return dResponse.isAcknowledged();
    }


    /**
     * 更新索引
     *
     * @param map 更新字段信息
     * @throws Exception
     */
    public String updateDoc(Map<String, Object> map) throws Exception {
        //更新,判断是更新还是删除
        if ("Y".equalsIgnoreCase((String) map.get("isDeleted"))) {
            //删除
            DeleteResponse response = client.prepareDelete(INDEX_NAME, TYPE_NAME, (String) map.get("id")).execute().actionGet();
            return response.getId();
        } else {
            //更新
            UpdateRequest request = new UpdateRequest(INDEX_NAME, TYPE_NAME, (String) map.get("id"));
            map.remove("id");
            request.doc(map);
            UpdateResponse response = client.update(request).get();
            return response.getId();
        }
    }

    public String save(Map map) {
        String id = null;
        try {
            log.info("before save mail  {}", JSON.toJSONString(map));
            Date nowDate = new Date();
            map.put("sendTime", dateInfoFormat.get().format(nowDate));
            IndexResponse response = client.prepareIndex(INDEX_NAME, TYPE_NAME)
                    .setSource(map).get();
            id = response.getId();
            log.info("response status \t{}\t save  ", response.status());
        } catch (Exception e) {
            log.error("saving  got an exception\t{} {}", e.getMessage(), e);
        }
        return id;
    }

    private <T> List<T> search(QueryBuilder query, Class clazz){
        List<T> list = new ArrayList<>();
        SearchRequestBuilder requestBuilder = client.prepareSearch(INDEX_NAME).setTypes(TYPE_NAME).setQuery(query);
        SearchResponse response = requestBuilder.execute().actionGet();
        SearchHits hits = response.getHits();
        for (SearchHit searchHit : hits) {
            String json = searchHit.getSourceAsString();
            T entity = (T) JSONObject.parseObject( json, clazz);
            list.add(entity);
        }
        return list;
    }


}
